/*
 * @ProjectName: 编程学习
 * @Copyright:   2019 HangZhou Yi Dev, Ltd. All Right Reserved.
 * @address:     http://Yi.tech
 * @date:        2019/5/20 20:57
 * @email:       xiazhaoyang@live.com
 * @description: 本内容仅限于编程技术学习使用，转发请注明出处.
 */
package com.example.repo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.annotation.Resource;

/**
 * <p>
 * 资源服务配置
 * ResourceServerConfigurerAdapter用于保护oauth要开放的资源，同时主要作用于client端以及token的认证(Bearer auth)
 * </p>
 *
 * @author Yi
 * @version v1.0.0
 * @date 2019/5/20 20:57
 * @modificationHistory=========================逻辑或功能性重大变更记录
 * @modify By: {修改人} 2019/5/20
 * @modify reason: {方法名}:{原因}
 * ...
 */
@EnableResourceServer
@Configuration
public class ResourceSecurityConfig extends ResourceServerConfigurerAdapter {

    @Value("${security.oauth2.resource.id}")
    public String resourceId;

    @Resource
    public RemoteTokenServices remoteTokenServices;

    /**
     * 资源服务器承载资源[REST API]，客户端感兴趣的资源位于  /book/ 。
     *
     * @param http
     * @throws Exception
     * @EnableResourceServer注释，适用在OAuth2资源服务器， 实现了Spring Security的过滤器验证的请求传入OAuth2令牌。 
     * ResourceServerConfigurerAdapter类实现 ResourceServerConfigurer 提供的方法来
     * 调整 OAuth2安全保护的访问规则和路径。
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.requestMatchers().antMatchers("/book/**")
                .and()
                .authorizeRequests()
                .antMatchers("/book/**").authenticated();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //如果关闭 stateless，则 accessToken 使用时的 session id 会被记录，后续请求不携带 accessToken 也可以正常响应
        resources.resourceId(resourceId).stateless(true).tokenServices(remoteTokenServices);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}